/*
* @(#)VersionControlManager.java
*
* Copyright (c) 2003 DCIVision Ltd
* All rights reserved.
*
* This software is the confidential and proprietary information of DCIVision
* Ltd ("Confidential Information").  You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the license
* agreement you entered into with DCIVision Ltd.
*/
package com.dcivision.dms.core;

import java.io.InputStream;
import java.net.URLConnection;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dcivision.alert.bean.UpdateAlert;
import com.dcivision.alert.core.AdapterMaster;
import com.dcivision.alert.core.AlertManager;
import com.dcivision.audit.AuditTrailConstant;
import com.dcivision.audit.core.AuditTrailManager;
import com.dcivision.dms.DmsErrorConstant;
import com.dcivision.dms.DmsOperationConstant;
import com.dcivision.dms.bean.DmsCheckoutHistory;
import com.dcivision.dms.bean.DmsContent;
import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.bean.DmsDocumentDetail;
import com.dcivision.dms.bean.DmsDocumentIndexCache;
import com.dcivision.dms.bean.DmsVersion;
import com.dcivision.dms.bean.MtmDocumentRelationship;
import com.dcivision.dms.bean.MtmDocumentVersion;
import com.dcivision.dms.dao.DmsCheckoutHistoryDAObject;
import com.dcivision.dms.dao.DmsContentDAObject;
import com.dcivision.dms.dao.DmsDocumentDAObject;
import com.dcivision.dms.dao.DmsVersionDAObject;
import com.dcivision.dms.dao.MtmDocumentRelationshipDAObject;
import com.dcivision.dms.dao.MtmDocumentVersionDAObject;
import com.dcivision.framework.AdapterMasterFactory;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.FullTextIndexFactory;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.IDFactory;
import com.dcivision.framework.IndexManager;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;

/**
 * <p>Class Name:       VersionControlManager.java    </p>
 * <p>Description:      The class mainly handle the document versioning, such as checkout/checkin, version listing, etc. </p>
 * @author              Zoe Shum
 * @company             DCIVision Limited
 * @creation date       01/08/2003
 * @version             $Revision: 1.71.2.4 $
 */

public class VersionControlManager {

  public static final String REVISION = "$Revision: 1.71.2.4 $";

  protected Log log = LogFactory.getLog(this.getClass().getName());
  private SessionContainer sessionContainer;
  private Connection conn;
  private DmsContentStoreHandler contentStoreHandler = null;

  /**
   *  Constructor - Creates a new instance of VersionControlManager
   */
  public VersionControlManager(SessionContainer sessionContainer, Connection conn) {
    this.sessionContainer = sessionContainer;
    this.conn = conn;
  }

  /**
    *  Release - To release the variable in instance of VersionControlManager
    */
   public void release () {
     this.sessionContainer = null;
     this.conn = null;
     contentStoreHandler = null;
   }

  /**
   *  Checkouts the document in DMS; Create a CheckoutHistory record, and updates the document checkoutID
   *
   *  @param      checkoutType             The constant indiciates the type to be checkout.
   *  @param      document                 The (DmsDocument) object of the target checkout document.
   *  @return     DmsDocument              The (DmsDocument) of corresponding dmsDocument.
   *  @throws     ApplicationException     Throws when create operation fault.
   */
  public void checkoutDocument(String checkoutType, DmsDocument document) throws UnrelockableException, ApplicationException {
    checkoutDocument(checkoutType, document, true, true);
  }
  
  /**
   * @param checkoutType
   * @param document
   * @param isAuditTrail
   * @param isAlert
   * @throws UnrelockableException
   * @throws ApplicationException
   */
  public void checkoutDocument(String checkoutType, DmsDocument document,boolean isAuditTrail,boolean isAlert) throws UnrelockableException, ApplicationException {
    String version = DmsOperationConstant.DMS_TOP_VERSION;
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DmsCheckoutHistory existingHistory = this.getCurrentCheckoutDetail(document, version);
    if (existingHistory != null) {
      throw new UnrelockableException(DmsErrorConstant.DUPLICATE_FILE_CHECKOUT);
    }
    //Update version status on target document in top version
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
    DmsVersion dmsVersion = docOperationManager.updateDocumentVersion(document, version, checkoutType);

    //Create Check out history for target Document
    DmsCheckoutHistory history = new DmsCheckoutHistory();
    history.setCheckoutTime(Utility.getCurrentTimestamp());
    history.setCheckoutPersonID(sessionContainer.getUserRecordID());
    history.setDocumentID(dmsVersion.getDocumentID());
    history.setVersionID(dmsVersion.getID());
    history.setCheckoutStatus(DmsCheckoutHistory.CURRENT_RECORD);
    DmsCheckoutHistoryDAObject historyDAO = new DmsCheckoutHistoryDAObject(sessionContainer, conn);
    DmsCheckoutHistory newHistory = (DmsCheckoutHistory)historyDAO.insertObject(history);
    historyDAO=null;

    //Update Document Checkout Status
    document.setCheckoutID(newHistory.getID());
    document.setItemStatus(DmsVersion.EXCLUSIVE_LOCK);
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsDocument newDocument = (DmsDocument) dmsDocumentDAO.updateObject(document);

    //update the index
    //indexDocument(newDocument, null, GlobalConstant.OP_MODE_UPDATE);

    //send alert 
    if(isAlert){
      sendAlert(dmsDocumentDAO, document, docRetrievalManager);
    }
    
    dmsDocumentDAO=null;

    // log down in audit trail
    if (isAuditTrail && sessionContainer.getUserRecordID() != null && sessionContainer.getSessionID()!=null 
        && (!DmsDocument.TIF_ANNOTATION_TYPE.equals(document.getDocumentType())) ) {
      AuditTrailManager auditManager = new AuditTrailManager(sessionContainer, conn);
      auditManager.auditTrail(GlobalConstant.OBJECT_TYPE_DOCUMENT, document, AuditTrailConstant.ACCESS_TYPE_CHECK_OUT, document.getVersionNumber());
      auditManager.release();
    }

    docOperationManager.release();
  }
  
  /**
   * Checkin a document and create a new document version and update the checkout history.
   * 
   * @param autoLabel                true if update the version label by system LabelManager
   * @param checkinType              DmsOperationConstant.CREATE_NEW_CHECKIN
   * @param documentID               the dmsDocument Object ID for checkin
   * @param version                  new version of the checkin document
   * @param data                     InputStream data of the checkin document
   * @return new version create after checkin
   * @throws IdentityMismatchException it is thrown if the checkin user not same as the checkout user
   * <pre>
   *   IdentityMismatchException with the following message codes will be thrown
   *   DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH
   * </pre>
   * @throws UncheckinableException it is thrown if checkin a document that is not checkout(Except the document in 
   *                                personal)
   * <pre>
   * UncheckinableException with the following message codes will be thrown
   * DmsErrorConstant.CHECKIN_INAVAILABLE
   * </pre>
   * @throws ApplicationException
   * @see com.dcivision.dms.core.labelManager
   * @see com.dcivision.dms.bean.DmsVersion
   * @see com.dcivision.dms.core.VersionManager#checkinDocument(boolean autoLabel, String checkinType, Integer documentID, DmsVersion version, InputStream data, InputStream fullTextFileInputStream)
   */
  public DmsVersion checkinDocument(boolean autoLabel, String checkinType, Integer documentID, DmsVersion version, InputStream data) throws IdentityMismatchException, UncheckinableException, ApplicationException {
    return this.checkinDocument(autoLabel, checkinType, documentID, version, data, null);
  }  
  
  /**
   * Checkin a document and create a new document version and update the checkout history.
   * <P>
   * This method mainly handle the checkin of the scan document with separate full text inputstream
   * </P>
   * @param autoLabel                 true if update the version label by system LabelManager
   * @param checkinType               DmsOperationConstant.CREATE_NEW_CHECKIN
   * @param documentID                the dmsDocument Object ID for checkin
   * @param version                   new version of the checkin document
   * @param data                      InputStream data of the checkin document
   * @param fullTextFileInputStream   full text data inputStream mainly for scan document
   * @return new version create after checkin
   * @throws IdentityMismatchException it is thrown if the checkin user not same as the checkout user
   * <pre>
   *   IdentityMismatchException with the following message codes will be thrown
   *   DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH
   * </pre>
   * @throws UncheckinableException it is thrown if checkin a document that is not checkout(Except the document in 
   *                                personal)
   * <pre>
   * UncheckinableException with the following message codes will be thrown
   * DmsErrorConstant.CHECKIN_INAVAILABLE
   * </pre>
   * @throws ApplicationException
   * @see com.dcivision.dms.core.labelManager
   * @see com.dcivision.dms.bean.DmsVersion
   */
  public DmsVersion checkinDocument(boolean autoLabel, String checkinType, Integer documentID, DmsVersion version, InputStream data, InputStream fullTextFileInputStream) throws IdentityMismatchException, UncheckinableException, ApplicationException {
    DocumentValidateManager docValidateManager = new DocumentValidateManager(sessionContainer, conn);
    // check if the uploaded file is empty content or does not exist.
    docValidateManager.checkDocumentIsEmptyContent(data);
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsVersion newVersion = null;
//    try {
      log.info("checkin document ID = " +documentID+" version parent ID -- " + version.getParentID());
      DmsDocument document = (DmsDocument) dmsDocumentDAO.getObjectByID(documentID);
      document.setCurFunctionCode(SystemFunctionConstant.DMS_PUBLIC_FOLDER);
      document.setItemSize(version.getItemSize());
      document.setRealDocumentName(version.getCheckinFileName());
      //Bill add for EIP-1958
      docValidateManager.checkStorageLimitAvailableInWorkflow(document);
      log.debug("Available space exists for current document");

      DmsCheckoutHistory checkoutHistory = getCurrentCheckoutDetail(document, DmsOperationConstant.DMS_TOP_VERSION);
      DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
      DmsDocument rootDocument = docRetrievalManager.getRootFolderByRootID(document.getRootID());
      if (! (DmsOperationConstant.DMS_PERSONAL_ROOT.equals(rootDocument.getDocumentName()) && rootDocument.getOwnerID().intValue() == sessionContainer.getUserRecordID().intValue())) {
        if (checkoutHistory != null) {  //by pass the check in person checking
          if (!DmsOperationConstant.DMS_RECORD_EMPTY.equals(document.getRecordStatus())){
            if (!sessionContainer.getUserRecordID().equals(checkoutHistory.getCheckoutPersonID())) {
              throw new IdentityMismatchException(DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH);
            }
          }
        } else {
          throw new UncheckinableException(DmsErrorConstant.CHECKIN_INAVAILABLE);
        }
      }
      LabelManager labelManager = new LabelManager(sessionContainer, conn);
      if (autoLabel) {
        labelManager.setVersion(version);
        labelManager.process();
      }
      if (DmsOperationConstant.DMS_RECORD_EMPTY.equals(document.getRecordStatus())){
        newVersion = this.updateVersionOnEmptyFileContent(document, version, data, fullTextFileInputStream);
      }else{
        newVersion = this.createVersion(document, version, data);
      }
      DmsCheckoutHistoryDAObject historyDAO = new DmsCheckoutHistoryDAObject(sessionContainer, conn);
      if (GlobalConstant.RECORD_PENDING.equals(version.getRecordStatus()) //not update checkout status and item status, update from Workflow
          && DmsOperationConstant.CREATE_NEW_CHECKIN.equals(checkinType)) { //For Record with and Major Workflow.
        /* List historyList = historyDAO.getObjectByVersionAndCheckoutStatus(version.getID(), DmsCheckoutHistory.CURRENT_RECORD);
         DmsCheckoutHistory history = (DmsCheckoutHistory) historyList.get(0);*/
        //history.setCheckoutStatus(DmsCheckoutHistory.HISTORY_RECORD);
        checkoutHistory.setCheckinTime(new Timestamp(System.currentTimeMillis()));
        historyDAO.updateObject(checkoutHistory);

      } else { //without workflow or personal folder
        // resume the items status
        newVersion.setItemStatus(DmsVersion.AVAILABLE_STATUS);
        //TODO: itemDAO.updateObject(newVersion);
        if (! (DmsOperationConstant.DMS_PERSONAL_ROOT.equals(rootDocument.getDocumentName())
               && rootDocument.getOwnerID().intValue() == sessionContainer.getUserRecordID().intValue())) {

          /*List historyList = historyDAO.getObjectByVersionAndCheckoutStatus(version.getID(), DmsCheckoutHistory.CURRENT_RECORD);
           log.debug("historyList = " + historyList.size());
               DmsCheckoutHistory history = (DmsCheckoutHistory) historyList.get(0);*/
          checkoutHistory.setCheckoutStatus(DmsCheckoutHistory.HISTORY_RECORD);
          checkoutHistory.setCheckinTime(new Timestamp(System.currentTimeMillis()));
          historyDAO.updateObject(checkoutHistory);
        }
      }
//log.debug("document.getParentID() = " + document.getParentID());
      //Document Checking Alert
      sendAlert(dmsDocumentDAO, document, docRetrievalManager);

      // log down in audit trail
      if (sessionContainer.getUserRecordID() != null && sessionContainer.getSessionID()!=null && (!DmsDocument.TIF_ANNOTATION_TYPE.equals(document.getDocumentType()))) {
        AuditTrailManager auditManager = new AuditTrailManager(sessionContainer, conn);
        auditManager.auditTrail(GlobalConstant.OBJECT_TYPE_DOCUMENT, document, AuditTrailConstant.ACCESS_TYPE_CHECK_IN, newVersion.getVersionNumber());
        auditManager.release();
      }
      dmsDocumentDAO=null;
      historyDAO=null;
      docValidateManager.release();

      return newVersion;
  }

  private void sendAlert(DmsDocumentDAObject dmsDocumentDAO, DmsDocument document, DocumentRetrievalManager docRetrievalManager) throws ApplicationException {
    DmsDocument parentDoc = (DmsDocument) dmsDocumentDAO.getObjectByID(document.getParentID());
    AdapterMaster am = AdapterMasterFactory.getAdapterMaster(sessionContainer, conn);
    try {
     // am.call(UpdateAlert.DOCUMENT_TYPE, parentDoc.getID(), UpdateAlert.UPDATE_ACTION, document.getDocumentName(), null, null, null, document.getID());
      am.call(UpdateAlert.DOCUMENT_TYPE, document.getID(), UpdateAlert.UPDATE_ACTION, document.getDocumentName(), null, null, null);
      if(docRetrievalManager.hasRelationship(document.getID(),null)){
        MtmDocumentRelationshipDAObject dmsMtmDocumentRelationshipDAO = new MtmDocumentRelationshipDAObject (sessionContainer, conn);
        AlertManager alertManager = new AlertManager(sessionContainer, conn);
        List relationList=dmsMtmDocumentRelationshipDAO.getListByIDRelationType(document.getID(),null);
          List inRelationList=dmsMtmDocumentRelationshipDAO.getListByRelationIDRelationType(document.getID(),null);
          List alertList=new ArrayList();
          if(!Utility.isEmpty(relationList)){
              for(int i=0;i<relationList.size();i++){
            alertList = alertManager.listUpdateAlertByObjectTypeObjectIDAndAction(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)relationList.get(i)).getDocumentID(),UpdateAlert.MODIFY_RELATED_DOC);
                if(!Utility.isEmpty(alertList)){
                    am.call(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)relationList.get(i)).getDocumentID(),UpdateAlert.MODIFY_RELATED_DOC,document.getDocumentName(),
                null,null,null,document.getID());
                 }
          }
         }
        if(!Utility.isEmpty(inRelationList)){
        for(int i=0;i<inRelationList.size();i++){
              alertList= alertManager.listUpdateAlertByObjectTypeObjectIDAndAction(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)inRelationList.get(i)).getRelatedDocumentID(),UpdateAlert.MODIFY_RELATED_DOC);
              if(!Utility.isEmpty(alertList)){
                  am.call(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)inRelationList.get(i)).getRelatedDocumentID(),UpdateAlert.MODIFY_RELATED_DOC,document.getDocumentName(),
              null,null,null,document.getID());
              }
            }
        }
      }
        am.release();
    } catch (Exception e) {
      log.error(e, e);
    }
  }
  
  /**
    * Checkin a document and create a new document version and update the checkout history.
    * <P>
    * This method handle the check in document that the check in document name is different 
    * from original one and update the ext (extension) of the DmsContent
    * </P>
    * @param autoLabel                 true if update the version label by system LabelManager
    * @param checkinType               DmsOperationConstant.CREATE_NEW_CHECKIN
    * @param documentID                the dmsDocument Object ID for checkin
    * @param version                   new version of the checkin document
    * @param data                      InputStream data of the checkin document
    * @param realDocumentName          checkin real document name
    * @return new version create after checkin
    * @throws IdentityMismatchException it is thrown if the checkin user not same as the checkout user
    * <pre>
    *   IdentityMismatchException with the following message codes will be thrown
    *   DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH
    * </pre>
    * @throws UncheckinableException it is thrown if checkin a document that is not checkout(Except the document in 
    *                                personal)
    * <pre>
    * UncheckinableException with the following message codes will be thrown
    * DmsErrorConstant.CHECKIN_INAVAILABLE
    * </pre>
    * @throws ApplicationException
    * @see com.dcivision.dms.core.labelManager
    * @see com.dcivision.dms.bean.DmsVersion
    */
  
  public DmsVersion checkinDocumentName(boolean autoLabel, String checkinType, Integer documentID, DmsVersion version, InputStream data, String realDocumentName) throws IdentityMismatchException, UncheckinableException, ApplicationException {
    return this.checkinDocumentName(autoLabel, checkinType, documentID, version, data, null,realDocumentName);
  }  
  
  /**
   * Checkin a document and create a new document version and update the checkout history.
   * <P>
   * This method mainly handles the checkin of the scan document with separate full text inputstream
   * This method handle the check in document that the check in document name is different 
   * from original one and update the ext (extension) of the DmsContent
   * </P>
   * @param autoLabel                 true if update the version label by system LabelManager
   * @param checkinType               DmsOperationConstant.CREATE_NEW_CHECKIN
   * @param documentID                the dmsDocument Object ID for checkin
   * @param version                   new version of the checkin document
   * @param data                      InputStream data of the checkin document
   * @param fullTextFileInputStream   full text data inputStream mainly for scan document
   * @param realDocumentName          checkin real document name
   * @return new version create after checkin
   * @throws IdentityMismatchException it is thrown if the checkin user not same as the checkout user
   * <pre>
   *   IdentityMismatchException with the following message codes will be thrown
   *   DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH
   * </pre>
   * @throws UncheckinableException it is thrown if checkin a document that is not checkout(Except the document in 
   *                                personal)
   * <pre>
   * UncheckinableException with the following message codes will be thrown
   * DmsErrorConstant.CHECKIN_INAVAILABLE
   * </pre>
   * @throws ApplicationException
   * @see com.dcivision.dms.core.labelManager
   * @see com.dcivision.dms.bean.DmsContent
  */
  public DmsVersion checkinDocumentName(boolean autoLabel, String checkinType, Integer documentID, DmsVersion version, InputStream data, InputStream fullTextFileInputStream, String realDocumentName) throws IdentityMismatchException, UncheckinableException, ApplicationException {
    DocumentValidateManager docValidateManager = new DocumentValidateManager(sessionContainer, conn);
    // check if the uploaded file is empty content or does not exist.
    docValidateManager.checkDocumentIsEmptyContent(data);
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsVersion newVersion = null;
//    try {
      log.info("checkin document ID = " +documentID+" version parent ID -- " + version.getParentID());
      DmsDocument document = (DmsDocument) dmsDocumentDAO.getObjectByID(documentID);
      document.setCurFunctionCode(SystemFunctionConstant.DMS_PUBLIC_FOLDER);
      document.setItemSize(version.getItemSize());
      document.setRealDocumentName(realDocumentName);
      docValidateManager.checkStorageLimitAvailable(document);
      log.debug("Available space exists for current document");

      DmsCheckoutHistory checkoutHistory = getCurrentCheckoutDetail(document, DmsOperationConstant.DMS_TOP_VERSION);
      DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
      DmsDocument rootDocument = docRetrievalManager.getRootFolderByRootID(document.getRootID());
      if (! (DmsOperationConstant.DMS_PERSONAL_ROOT.equals(rootDocument.getDocumentName()) && rootDocument.getOwnerID().intValue() == sessionContainer.getUserRecordID().intValue())) {
        if (checkoutHistory != null) {  //by pass the check in person checking
          if (!DmsOperationConstant.DMS_RECORD_EMPTY.equals(document.getRecordStatus())){
            if (!sessionContainer.getUserRecordID().equals(checkoutHistory.getCheckoutPersonID())) {
              throw new IdentityMismatchException(DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH);
            }
          }
        } else {
          throw new UncheckinableException(DmsErrorConstant.CHECKIN_INAVAILABLE);
        }
      }
      LabelManager labelManager = new LabelManager(sessionContainer, conn);
      if (autoLabel) {
        labelManager.setVersion(version);
        labelManager.process();
      }
      if (DmsOperationConstant.DMS_RECORD_EMPTY.equals(document.getRecordStatus())){
        newVersion = this.updateVersionOnEmptyFileContentName(document, version, data, fullTextFileInputStream);
      }else{
        newVersion = this.createVersionName(document, version, data);
      }
      DmsCheckoutHistoryDAObject historyDAO = new DmsCheckoutHistoryDAObject(sessionContainer, conn);
      if (GlobalConstant.RECORD_PENDING.equals(version.getRecordStatus()) //not update checkout status and item status, update from Workflow
          && DmsOperationConstant.CREATE_NEW_CHECKIN.equals(checkinType)) { //For Record with and Major Workflow.
        /* List historyList = historyDAO.getObjectByVersionAndCheckoutStatus(version.getID(), DmsCheckoutHistory.CURRENT_RECORD);
         DmsCheckoutHistory history = (DmsCheckoutHistory) historyList.get(0);*/
        //history.setCheckoutStatus(DmsCheckoutHistory.HISTORY_RECORD);
        checkoutHistory.setCheckinTime(new Timestamp(System.currentTimeMillis()));
        historyDAO.updateObject(checkoutHistory);

      } else { //without workflow or personal folder
        // resume the items status
        newVersion.setItemStatus(DmsVersion.AVAILABLE_STATUS);
        //TODO: itemDAO.updateObject(newVersion);
        if (! (DmsOperationConstant.DMS_PERSONAL_ROOT.equals(rootDocument.getDocumentName())
               && rootDocument.getOwnerID().intValue() == sessionContainer.getUserRecordID().intValue())) {

          /*List historyList = historyDAO.getObjectByVersionAndCheckoutStatus(version.getID(), DmsCheckoutHistory.CURRENT_RECORD);
           log.debug("historyList = " + historyList.size());
               DmsCheckoutHistory history = (DmsCheckoutHistory) historyList.get(0);*/
          checkoutHistory.setCheckoutStatus(DmsCheckoutHistory.HISTORY_RECORD);
          checkoutHistory.setCheckinTime(new Timestamp(System.currentTimeMillis()));
          historyDAO.updateObject(checkoutHistory);
        }
      }
//log.debug("document.getParentID() = " + document.getParentID());
      //Document Checking Alert
      DmsDocument parentDoc = (DmsDocument) dmsDocumentDAO.getObjectByID(document.getParentID());
      AdapterMaster am = AdapterMasterFactory.getAdapterMaster(sessionContainer, conn);
      try {
        am.call(UpdateAlert.DOCUMENT_TYPE, parentDoc.getID(), UpdateAlert.UPDATE_ACTION, document.getDocumentName(), null, null, null, document.getID());
        am.call(UpdateAlert.DOCUMENT_TYPE, document.getID(), UpdateAlert.UPDATE_ACTION, document.getDocumentName(), null, null, null);
        if(docRetrievalManager.hasRelationship(document.getID(),null)){
          MtmDocumentRelationshipDAObject dmsMtmDocumentRelationshipDAO = new MtmDocumentRelationshipDAObject (sessionContainer, conn);
          AlertManager alertManager = new AlertManager(sessionContainer, conn);
          List relationList=dmsMtmDocumentRelationshipDAO.getListByIDRelationType(document.getID(),null);
              List inRelationList=dmsMtmDocumentRelationshipDAO.getListByRelationIDRelationType(document.getID(),null);
              List alertList=new ArrayList();
              if(!Utility.isEmpty(relationList)){
                    for(int i=0;i<relationList.size();i++){
              alertList = alertManager.listUpdateAlertByObjectTypeObjectIDAndAction(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)relationList.get(i)).getDocumentID(),UpdateAlert.MODIFY_RELATED_DOC);
                      if(!Utility.isEmpty(alertList)){
                            am.call(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)relationList.get(i)).getDocumentID(),UpdateAlert.MODIFY_RELATED_DOC,document.getDocumentName(),
                    null,null,null,document.getID());
                       }
            }
             }
            if(!Utility.isEmpty(inRelationList)){
          for(int i=0;i<inRelationList.size();i++){
                    alertList= alertManager.listUpdateAlertByObjectTypeObjectIDAndAction(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)inRelationList.get(i)).getRelatedDocumentID(),UpdateAlert.MODIFY_RELATED_DOC);
                    if(!Utility.isEmpty(alertList)){
                          am.call(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)inRelationList.get(i)).getRelatedDocumentID(),UpdateAlert.MODIFY_RELATED_DOC,document.getDocumentName(),
                  null,null,null,document.getID());
                    }
                  }
            }
          }
              am.release();
      } catch (Exception e) {
        log.error(e, e);
      }

      // log down in audit trail
      if (sessionContainer.getUserRecordID() != null && sessionContainer.getSessionID()!=null  && (!DmsDocument.TIF_ANNOTATION_TYPE.equals(document.getDocumentType()))) {
        AuditTrailManager auditManager = new AuditTrailManager(sessionContainer, conn);
        auditManager.auditTrail(GlobalConstant.OBJECT_TYPE_DOCUMENT, document, AuditTrailConstant.ACCESS_TYPE_CHECK_IN, newVersion.getVersionNumber());
        auditManager.release();
      }
      dmsDocumentDAO=null;
      historyDAO=null;
      docValidateManager.release();

      return newVersion;
  }


  /**
   * Gets the total number of versions of a dmsDocument
   * @param documentID the dmsDocument Object
   * @return total number of versions
   * @throws ApplicationException
   */
  public int getTotalVerionsByDocumentID(Integer documentID) throws ApplicationException{
    int version = 0;
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    version = dmsDocumentDAO.getNoOfVersion(documentID);
    dmsDocumentDAO=null;
    return version;
  }

  /**
   * Creates a new version of a checkin document, the dmsContent and the checkin physical files
   * also create.
   * 
   * @param document the dmsDocument object check in
   * @param version  the new version created
   * @param data     the checkin document data InputStream
   * @return the new version created after checkin
   * @throws ApplicationException
   * @see com.dcivision.dms.bean.DmsVersion
   */
  public DmsVersion createVersion(DmsDocument document, DmsVersion version, InputStream data) throws ApplicationException {
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
    DmsContentManager dmsContentManager = new DmsContentManager(sessionContainer, conn);
    
    // define version
    DmsVersionDAObject versionDAO = new DmsVersionDAObject(sessionContainer, conn);
    //Get the parent version list
    List versionList = versionDAO.getParentVersionsListByParentIDByDocumentID(version.getParentID(), document.getID());
    int versionNumber = 1;
    if (versionList.size() > 0) {
      DmsVersion latestVersion = (DmsVersion) versionList.get(0);  //get latest version obj, and see it is a major or minor version
      if (version.getParentID().intValue() == 0){
        //Version number increment if the target check-in version is a major
        versionNumber = TextUtility.parseInteger(latestVersion.getVersionNumber()) + 1;
      }else{
        //Version number increment if the target check-in version is a minor
        String latestVersionNo = latestVersion.getVersionNumber();
        String subVersionNo = latestVersionNo.substring(latestVersionNo.indexOf(".")+1, latestVersionNo.length());
        versionNumber = TextUtility.parseInteger(subVersionNo) + 1;
      }
    }
    String tmpVersionNo = TextUtility.formatInteger(versionNumber);

    // create abstract content record
    DmsContentDAObject contentDAO = new DmsContentDAObject(sessionContainer, conn);
    String contentType = URLConnection.guessContentTypeFromName(document.getRealDocumentName());
//    String contentType = URLConnection.guessContentTypeFromName(document.getDocumentName());
    DmsDocumentNameConvertor documentNameConvertor = null;
    try {
      //To create the version number in minor style
      if (version.getParentID().intValue() != 0) {
        DmsVersion parentVersion = (DmsVersion)versionDAO.getObjectByID(version.getParentID());
        //joan.xiong update code for bug EIP-1191 by 2006/12/22
        //tmpVersionNo = parentVersion.getVersionNumber().toString() + "." + versionNumber;
        if(parentVersion.getVersionNumber().indexOf(".")>-1){
        	String integer = parentVersion.getVersionNumber().substring(0,parentVersion.getVersionNumber().indexOf("."));
        	String traction = "";
        	if(!Utility.isEmpty(versionList)){
        		tmpVersionNo = integer+"."+versionNumber;
        	}else{
            	traction = parentVersion.getVersionNumber().substring(parentVersion.getVersionNumber().indexOf(".")+1);
            	traction = new Integer(new Integer(traction).intValue()+versionNumber).toString();
            	tmpVersionNo = integer+"."+traction;
        	}
        }else{
        	tmpVersionNo = parentVersion.getVersionNumber().toString() + "." + versionNumber;
        }
        //joan.xiong update code end
      }
      document.setVersionNumber(tmpVersionNo);//used to create the converted name
      
      documentNameConvertor = (DmsDocumentNameConvertor) Class.forName(
        SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS)).newInstance();
      
    } catch (Exception e) {
      log.error("Name Convertor class not found.", e);
      throw new ApplicationException(DmsErrorConstant.NAME_CONVERTOR_CLASS_NOT_FOUND);
    }


    DmsContent content = new DmsContent();
    content.setContentType(contentType);
    String docExt = "";
    if (document.getRealDocumentName().lastIndexOf(".") > 0) {
      docExt = document.getRealDocumentName().substring(document.getRealDocumentName().lastIndexOf("."));
    }
//    if (document.getDocumentName().lastIndexOf(".") > 0) {
//      docExt = document.getDocumentName().substring(document.getDocumentName().lastIndexOf("."));
//    }
    if (docExt != null && docExt.length() > 0) {
      docExt = docExt.substring(1).toUpperCase();
    }
    content.setExt(docExt);
    content = (DmsContent) contentDAO.insertObject(content);

    //create version
    version.setVersionNumber(tmpVersionNo);
    version.setContentID(content.getID());
    version.setItemStatus(DmsVersion.AVAILABLE_STATUS);
    //version.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
    //version.setParentID(new Integer(0));
    DmsVersion newVersion = (DmsVersion) versionDAO.insertObject(version);

    // create version to document relation
    MtmDocumentVersionDAObject docVersionDAO = new MtmDocumentVersionDAObject(sessionContainer, conn);
    MtmDocumentVersion docVersion = new MtmDocumentVersion();
    docVersion.setDocumentID(document.getID());
    docVersion.setVersionID(newVersion.getID());
    docVersion = (MtmDocumentVersion) docVersionDAO.insertObject(docVersion);

    //update document info
    document.setItemSize(newVersion.getItemSize());
    document.setItemStatus(newVersion.getItemStatus());
    document.setCheckoutID(null);
    document.setContentID(newVersion.getContentID());
    document.setReferenceNo(version.getReferenceNo());
    document.setDescription(version.getDescription());

    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsDocument newDocument = (DmsDocument)dmsDocumentDAO.updateObject(document);
    dmsDocumentDAO=null;
    
    String convertedName = "";
    //use the shortDocumentNameConvertor
    String  convertClassName=SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS);
    if(convertClassName.indexOf("ShortDocumentNameConvertor")>0){
      DmsDocument tempDmsDocument = new DmsDocument(); 
      tempDmsDocument.setID(content.getID());
      convertedName = documentNameConvertor.encryptDocumentName(tempDmsDocument);
    }
    // use the standardDocumentNameConvertor
    else{
      convertedName = documentNameConvertor.encryptDocumentName(document);
    }    

    this.contentStoreHandler = dmsContentManager.writeDmsDocumentStoreContent(document,convertedName,data);
    Integer segmentNoInt = (Integer)contentStoreHandler.getProperty(DmsContentStoreHandler.SEGMENTNUM_PROPERTY);
    content.setSegmentNO(segmentNoInt);
    content.setConvertedName(convertedName);
    contentDAO.updateObject(content);    
    

    try { data.close(); } catch (Exception ignore) { data = null; }
    data = contentStoreHandler.readStream();

    newDocument.setVersionFileName(version.getCheckinFileName());
    
    //indexDocument(newDocument, data, GlobalConstant.OP_MODE_UPDATE);
    DmsDocumentIndexCache indexCache = new DmsDocumentIndexCache(newDocument.getID(),DmsDocumentIndexCache.ACTION_MODE_CHECKIN, null, null);
    docOperationManager.indexLUCENE(indexCache, newDocument, content, data);

    return newVersion;
  }
  
  /**
   * Creates a new version of a checkin document, the dmsContent and the checkin physical files
   * also create. The checkin document, its file extension will be store in DmsContent extension
   * 
   * 
   * @param document the dmsDocument object check in
   * @param version  the new version created
   * @param data     the checkin document data InputStream
   * @return the new version created after checkin
   * @throws ApplicationException
   * @see com.dcivision.dms.bean.DmsContent
   * 
   */
  public DmsVersion createVersionName(DmsDocument document, DmsVersion version, InputStream data) throws ApplicationException {
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
    DmsContentManager dmsContentManager = new DmsContentManager(sessionContainer, conn);
    
    // define version
    DmsVersionDAObject versionDAO = new DmsVersionDAObject(sessionContainer, conn);
    //Get the parent version list
    List versionList = versionDAO.getParentVersionsListByParentIDByDocumentID(version.getParentID(), document.getID());
    int versionNumber = 1;
    if (versionList.size() > 0) {
      DmsVersion latestVersion = (DmsVersion) versionList.get(0);  //get latest version obj, and see it is a major or minor version
      if (version.getParentID().intValue() == 0){
        //Version number increment if the target check-in version is a major
        versionNumber = TextUtility.parseInteger(latestVersion.getVersionNumber()) + 1;
      }else{
        //Version number increment if the target check-in version is a minor
        String latestVersionNo = latestVersion.getVersionNumber();
        String subVersionNo = latestVersionNo.substring(latestVersionNo.indexOf(".")+1, latestVersionNo.length());
        versionNumber = TextUtility.parseInteger(subVersionNo) + 1;
      }
    }
    String tmpVersionNo = TextUtility.formatInteger(versionNumber);

    // create abstract content record
    DmsContentDAObject contentDAO = new DmsContentDAObject(sessionContainer, conn);
    String contentType = URLConnection.guessContentTypeFromName(document.getRealDocumentName());
    DmsDocumentNameConvertor documentNameConvertor = null;
    try {
      //To create the version number in minor style
      if (version.getParentID().intValue() != 0) {
        DmsVersion parentVersion = (DmsVersion)versionDAO.getObjectByID(version.getParentID());
        tmpVersionNo = parentVersion.getVersionNumber().toString() + "." + versionNumber;
      }
      document.setVersionNumber(tmpVersionNo);//used to create the converted name
      documentNameConvertor = (DmsDocumentNameConvertor) Class.forName(
        SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS)).newInstance();
    } catch (Exception e) {
      log.error("Name Convertor class not found.", e);
      throw new ApplicationException(DmsErrorConstant.NAME_CONVERTOR_CLASS_NOT_FOUND);
    }
    //String convertedName = documentNameConvertor.encryptDocumentName(document);
    
    //  lee.lv add for error 'check in failure' in 2006/04/28
    Integer contentID= IDFactory.getInstance().getNextSequence("DMS_CONTENT");
    String  convertClassName = SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS);
    String convertedName = "";
    if(convertClassName.indexOf("ShortDocumentNameConvertor")>0){
      DmsDocument tempDmsDocument = new DmsDocument(); 
      tempDmsDocument.setID(contentID);
      convertedName = documentNameConvertor.encryptDocumentName(tempDmsDocument);
    }else{
      convertedName = documentNameConvertor.encryptDocumentName(document);  
    }
    //  lee.lv add end

    DmsContent content = new DmsContent();
    content.setID(contentID);
    content.setConvertedName(convertedName);
    content.setContentType(contentType);
    String docExt = "";
    if (document.getRealDocumentName().lastIndexOf(".") > 0) {
      docExt = document.getRealDocumentName().substring(document.getRealDocumentName().lastIndexOf("."));
    }
    if (docExt != null && docExt.length() > 0) {
      docExt = docExt.substring(1).toUpperCase();
    }
    content.setExt(docExt);
    content = (DmsContent) contentDAO.insertObject(content);

    //create version
    version.setVersionNumber(tmpVersionNo);
    version.setContentID(content.getID());
    version.setItemStatus(DmsVersion.AVAILABLE_STATUS);
    //version.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
    //version.setParentID(new Integer(0));
    DmsVersion newVersion = (DmsVersion) versionDAO.insertObject(version);

    // create version to document relation
    MtmDocumentVersionDAObject docVersionDAO = new MtmDocumentVersionDAObject(sessionContainer, conn);
    MtmDocumentVersion docVersion = new MtmDocumentVersion();
    docVersion.setDocumentID(document.getID());
    docVersion.setVersionID(newVersion.getID());
    docVersion = (MtmDocumentVersion) docVersionDAO.insertObject(docVersion);

    //update document info
    document.setItemSize(newVersion.getItemSize());
    document.setItemStatus(newVersion.getItemStatus());
    document.setCheckoutID(null);
    document.setContentID(newVersion.getContentID());
    document.setReferenceNo(version.getReferenceNo());
    document.setDescription(version.getDescription());

    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsDocument newDocument = (DmsDocument)dmsDocumentDAO.updateObject(document);
    dmsDocumentDAO=null;

    // create physical file
    this.contentStoreHandler = dmsContentManager.writeDmsDocumentStoreContent(document,convertedName,data);
    
    Integer segmentNoInt = (Integer)contentStoreHandler.getProperty(DmsContentStoreHandler.SEGMENTNUM_PROPERTY);
    content.setSegmentNO(segmentNoInt);
    content.setConvertedName(convertedName);
    contentDAO.updateObject(content);    
    
    try { data.close(); } catch (Exception ignore) { data = null; }
    data = contentStoreHandler.readStream();

    newDocument.setVersionFileName(version.getCheckinFileName());
    // indexDocument(newDocument, data, GlobalConstant.OP_MODE_UPDATE);
    DmsDocumentIndexCache indexCache = new DmsDocumentIndexCache(newDocument.getID(),DmsDocumentIndexCache.ACTION_MODE_CHECKIN, null, null);
    docOperationManager.indexLUCENE(indexCache, newDocument, content, data);
    

    return newVersion;
  }

  /**
   * used to attached the content file for empty content document.
   * 
   * <P>
   * This method handle to checkin of the file to an reference document (file with empty content),
   * the version of the reference will be updated and the content will also create.
   * </P>
   *
   * @param document      The document object.
   * @param version       The document's version object
   * @param InputStream   The stream data for the document
   * @param fullTextFileInputStream   The full text data InputStream
   * @throws ApplicationException
   * <pre>
   *   ApplicationException with the following message codes will be thrown
   *   DmsErrorConstant.NAME_CONVERTOR_CLASS_NOT_FOUND - Physical file handle class not found
   * </pre>
   * @see com.dcivision.dms.core.DmsErrorConstant
   * @see com.dcivision.dms.bean.DmsContent
   * @see com.dcivision.dms.bean.DmsDocument
   * 
   */
  public DmsVersion updateVersionOnEmptyFileContent(DmsDocument document, DmsVersion version, InputStream data, InputStream fullTextFileInputStream) throws ApplicationException {
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
    DmsContentManager dmsContentManager = new DmsContentManager(sessionContainer, conn);

    // update version
    DmsVersionDAObject versionDAO = new DmsVersionDAObject(sessionContainer, conn);
    DmsVersion oriVersion = (DmsVersion) versionDAO.getTopVersionByDocumentID(document.getID());

    // create abstract content record
    DmsContentDAObject contentDAO = new DmsContentDAObject(sessionContainer, conn);
    String contentType = URLConnection.guessContentTypeFromName(document.getDocumentName());
    DmsDocumentNameConvertor documentNameConvertor = null;
    String tmpVersionNo="";
    try {
      document.setVersionNumber(oriVersion.getVersionNumber());//used to create the converted name
      documentNameConvertor = (DmsDocumentNameConvertor) Class.forName(
        SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS)).newInstance();
    } catch (Exception e) {
      log.error("Name Convertor class not found.", e);
      throw new ApplicationException(DmsErrorConstant.NAME_CONVERTOR_CLASS_NOT_FOUND);
    }
 
    DmsContent content = (DmsContent)contentDAO.getObjectByID(oriVersion.getContentID());
    content.setContentType(contentType);
    String docExt = "";
    if (document.getDocumentName().lastIndexOf(".") > 0) {
      docExt = document.getDocumentName().substring(document.getDocumentName().lastIndexOf("."));
    }
    if (docExt != null && docExt.length() > 0) {
      docExt = docExt.substring(1).toUpperCase();
    }
    content.setExt(docExt);
    content = (DmsContent) contentDAO.updateObject(content);

    //create version
    //oriVersion.setVersionNumber(tmpVersionNo);
    oriVersion.setContentID(content.getID());
    oriVersion.setItemStatus(DmsVersion.AVAILABLE_STATUS);
    oriVersion.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
    oriVersion.setItemSize(version.getItemSize());
    DmsVersion newVersion = (DmsVersion) versionDAO.updateObject(oriVersion);

    //update document info
    document.setItemSize(newVersion.getItemSize());
    document.setItemStatus(newVersion.getItemStatus());
    document.setCheckoutID(null);
    document.setContentID(newVersion.getContentID());
    String referenceNo = version.getReferenceNo();
    String description = version.getDescription();
    if (Utility.isEmpty(referenceNo)) {
      referenceNo = document.getReferenceNo();
    }
    if (Utility.isEmpty(description)){
      description = version.getDescription();
    }
    document.setReferenceNo(referenceNo);
    document.setDescription(description);
    document.setRecordStatus(GlobalConstant.RECORD_STATUS_ACTIVE);
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsDocument newDocument = (DmsDocument)dmsDocumentDAO.updateObject(document);
    dmsDocumentDAO=null;

    // create physical file
    String convertedName = "";
    String convertClassName=SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS);
    if(convertClassName.indexOf("ShortDocumentNameConvertor")>0){
      DmsDocument tempDmsDocument = new DmsDocument(); 
      tempDmsDocument.setID(content.getID());
      convertedName = documentNameConvertor.encryptDocumentName(tempDmsDocument);
    }else{
      convertedName = documentNameConvertor.encryptDocumentName(document);
    }        
    
    this.contentStoreHandler = dmsContentManager.writeDmsDocumentStoreContent(document,convertedName,data);
    
    // update content
    Integer segmentNoInt = (Integer)contentStoreHandler.getProperty(DmsContentStoreHandler.SEGMENTNUM_PROPERTY);
    content.setSegmentNO(segmentNoInt);
    content.setConvertedName(convertedName);
    contentDAO.updateObject(content);    

    if (fullTextFileInputStream!=null) {  //For scan-in doc checkin
      log.debug("With OCR Full Text File.");
      //indexDocument(newDocument, data, GlobalConstant.OP_MODE_DELETE);
      newDocument.setScanDocumentForFullText(true);
      //Reset all index for this doc
      newDocument.setDocumentDetails(docRetrievalManager.getDocumentDetailList(newDocument.getID()));
      if (newDocument.getDocumentDetails()!=null && newDocument.getDocumentDetails().size()>0){
        DmsDocumentDetail docDetail = (DmsDocumentDetail) newDocument.getDocumentDetails().get(0);
        newDocument.setUserDefinedFieldID(docDetail.getUserDefinedFieldID());
      }
      //indexDocument(newDocument, fullTextFileInputStream, GlobalConstant.OP_MODE_INSERT);
      DmsDocumentIndexCache indexCache = new DmsDocumentIndexCache(newDocument.getID(),DmsDocumentIndexCache.ACTION_MODE_CHECKIN, DmsDocumentIndexCache.ACTION_TYPE_RUN_IMMEDIATELY, null);
      content.setExt("TXT");
      docOperationManager.indexLUCENE(indexCache, newDocument, content, fullTextFileInputStream);
    } else {
      log.debug("Without OCR Full Text File.");
      try { data.close(); } catch (Exception ignore) { data = null; }
      data = contentStoreHandler.readStream();
      //indexDocument(newDocument, data, GlobalConstant.OP_MODE_UPDATE);
      DmsDocumentIndexCache indexCache = new DmsDocumentIndexCache(newDocument.getID(),DmsDocumentIndexCache.ACTION_MODE_CHECKIN, DmsDocumentIndexCache.ACTION_TYPE_RUN_IMMEDIATELY, null);
      docOperationManager.indexLUCENE(indexCache, newDocument, content, data);
    }
    return newVersion;
  }
  
  /**
   * used to attached the content file for empty content document.
   * 
   * <P>
   * This method handle to checkin of the file to an reference document (file with empty content),
   * the version of the reference will be updated and the content will also create.
   * The check in document name which is different from the original one, the file extension will store
   * into the ext (Extension) of the DmsContent object
   * </P>
   *
   * @param document      The document object.
   * @param version       The document's version object
   * @param InputStream   The stream data for the document
   * @param fullTextFileInputStream   The full text data InputStream
   * @throws ApplicationException
   * <pre>
   *   ApplicationException with the following message codes will be thrown
   *   DmsErrorConstant.NAME_CONVERTOR_CLASS_NOT_FOUND - Physical file handle class not found
   * </pre>
   * @see com.dcivision.dms.core.DmsErrorConstant
   * @see com.dcivision.dms.bean.DmsContent
   * @see com.dcivision.dms.bean.DmsDocument
   * 
   */
  public DmsVersion updateVersionOnEmptyFileContentName(DmsDocument document, DmsVersion version, InputStream data, InputStream fullTextFileInputStream) throws ApplicationException {
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
    DmsContentManager dmsContentManager = new DmsContentManager(sessionContainer, conn);
    
    
    // update version
    DmsVersionDAObject versionDAO = new DmsVersionDAObject(sessionContainer, conn);
    DmsVersion oriVersion = (DmsVersion) versionDAO.getTopVersionByDocumentID(document.getID());

    // create abstract content record
    DmsContentDAObject contentDAO = new DmsContentDAObject(sessionContainer, conn);    
    String contentType = URLConnection.guessContentTypeFromName(document.getRealDocumentName());
    DmsDocumentNameConvertor documentNameConvertor = null;
    String tmpVersionNo="";
    try {
      document.setVersionNumber(oriVersion.getVersionNumber());//used to create the converted name
      documentNameConvertor = (DmsDocumentNameConvertor) Class.forName(
        SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS)).newInstance();
    } catch (Exception e) {
      log.error("Name Convertor class not found.", e);
      throw new ApplicationException(DmsErrorConstant.NAME_CONVERTOR_CLASS_NOT_FOUND);
    }

    DmsContent content = (DmsContent)contentDAO.getObjectByID(oriVersion.getContentID());
    content.setContentType(contentType);
    String docExt = "";
    if (document.getDocumentName().lastIndexOf(".") > 0) {
      docExt = document.getRealDocumentName().substring(document.getRealDocumentName().lastIndexOf("."));
    }
    if (docExt != null && docExt.length() > 0) {
      docExt = docExt.substring(1).toUpperCase();
    }
    content.setExt(docExt);
    content = (DmsContent) contentDAO.updateObject(content); 

    //create version
    //oriVersion.setVersionNumber(tmpVersionNo);
    oriVersion.setContentID(content.getID());
    oriVersion.setItemStatus(DmsVersion.AVAILABLE_STATUS);
    oriVersion.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
    oriVersion.setItemSize(version.getItemSize());
    oriVersion.setDescription(version.getDescription());
    DmsVersion newVersion = (DmsVersion) versionDAO.updateObject(oriVersion);

    //update document info
    document.setItemSize(newVersion.getItemSize());
    document.setItemStatus(newVersion.getItemStatus());
    document.setCheckoutID(null);
    document.setContentID(newVersion.getContentID());
    String referenceNo = version.getReferenceNo();
    String description = version.getDescription();
    if (Utility.isEmpty(referenceNo)) {
      referenceNo = document.getReferenceNo();
    }
    if (Utility.isEmpty(description)){
      description = version.getDescription();
    }
    document.setReferenceNo(referenceNo);
    document.setDescription(description);
    document.setRecordStatus(GlobalConstant.RECORD_STATUS_ACTIVE);
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsDocument newDocument = (DmsDocument)dmsDocumentDAO.updateObject(document);
    dmsDocumentDAO=null;

    // create physical file
    String convertedName = "";
    String convertClassName=SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS);
    if(convertClassName.indexOf("ShortDocumentNameConvertor")>0){
      DmsDocument tempDmsDocument = new DmsDocument(); 
      tempDmsDocument.setID(content.getID());
      convertedName = documentNameConvertor.encryptDocumentName(tempDmsDocument);
    }else{
      convertedName = documentNameConvertor.encryptDocumentName(document);
    }        
    
    this.contentStoreHandler = dmsContentManager.writeDmsDocumentStoreContent(document,convertedName,data);
    
    // update content
    Integer segmentNoInt = (Integer)contentStoreHandler.getProperty(DmsContentStoreHandler.SEGMENTNUM_PROPERTY);
    content.setSegmentNO(segmentNoInt);
    content.setConvertedName(convertedName);
    contentDAO.updateObject(content);  

    if (fullTextFileInputStream!=null) {  //For scan-in doc checkin
      log.debug("With OCR Full Text File.");
      //indexDocument(newDocument, data, GlobalConstant.OP_MODE_DELETE);
      newDocument.setScanDocumentForFullText(true);
      //Reset all index for this doc
      newDocument.setDocumentDetails(docRetrievalManager.getDocumentDetailList(newDocument.getID()));
      if (newDocument.getDocumentDetails()!=null && newDocument.getDocumentDetails().size()>0){
        DmsDocumentDetail docDetail = (DmsDocumentDetail) newDocument.getDocumentDetails().get(0);
        newDocument.setUserDefinedFieldID(docDetail.getUserDefinedFieldID());
      }
      DmsDocumentIndexCache indexCache = new DmsDocumentIndexCache(newDocument.getID(),DmsDocumentIndexCache.ACTION_MODE_CHECKIN, DmsDocumentIndexCache.ACTION_TYPE_RUN_IMMEDIATELY, null);
      content.setExt("TXT");
      docOperationManager.indexLUCENE(indexCache, newDocument, content, fullTextFileInputStream);
      //indexDocument(newDocument, fullTextFileInputStream, GlobalConstant.OP_MODE_INSERT);
    } else {
      log.debug("Without OCR Full Text File.");
      try { data.close(); } catch (Exception ignore) { data = null; }
      data = contentStoreHandler.readStream();
      //indexDocument(newDocument, data, GlobalConstant.OP_MODE_UPDATE);
      DmsDocumentIndexCache indexCache = new DmsDocumentIndexCache(newDocument.getID(),DmsDocumentIndexCache.ACTION_MODE_CHECKIN, DmsDocumentIndexCache.ACTION_TYPE_RUN_IMMEDIATELY, null);
      docOperationManager.indexLUCENE(indexCache, newDocument, content, data);
    }
    return newVersion;
  }


  /**
   * Unlocks the dmsDocument object when the checkout document is no update.  
   * <P>
   * The itemStatus of DmsDocument object and the DmsVersion object will set back to Active
   * and update the checkout History.
   * </P>
   * @param documentID the dmsDocument object to be unlock
   * @return the toppest version
   * @throws ApplicationException
   * @see com.dcivision.dms.bean.DmsCheckoutHistory
   */
  public DmsVersion unlockDocumentForNoUpdateCheckin(Integer documentID) throws ApplicationException {

    //update document info
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DmsDocument document = docRetrievalManager.getDocument(documentID);
    document.setItemStatus(DmsVersion.AVAILABLE_STATUS);
    document.setCheckoutID(null);

    /*
     * No-update-checkin will not update update_date or update_id
     * EIP-1438 07/01/11 LEE
     */
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    dmsDocumentDAO.documentSQLExecute("UPDATE", "ITEM_STATUS", DmsVersion.AVAILABLE_STATUS, document, false); 
    dmsDocumentDAO.documentSQLExecute("UPDATE", "CHECKOUT_ID", null, document, false); 
    dmsDocumentDAO = null;
    /*
     * EIP-1438 07/01/11 LEE
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
    DmsDocument newDocument = (DmsDocument)docOperationManager.updateDocument(document, false);
    docOperationManager.release();
    */
    
    DmsVersionDAObject dmsVersionDAO = new DmsVersionDAObject(sessionContainer, conn);
    DmsVersion dmsVersion = (DmsVersion) dmsVersionDAO.getTopVersionByDocumentID(documentID);
    dmsVersion.setItemStatus(DmsVersion.AVAILABLE_STATUS);
    dmsVersion = (DmsVersion) dmsVersionDAO.updateObject(dmsVersion);

    DmsCheckoutHistoryDAObject historyDAO = new DmsCheckoutHistoryDAObject(sessionContainer, conn);
    List currentLocker = historyDAO.getObjectByVersionAndCheckoutStatus(dmsVersion.getID(), DmsCheckoutHistory.CURRENT_RECORD);
    
    DmsCheckoutHistory oldcheckoutHistory = getCurrentCheckoutDetail(document, DmsOperationConstant.DMS_TOP_VERSION);
    DmsDocument rootDocument = docRetrievalManager.getRootFolderByRootID(document.getRootID());
    if (! (DmsOperationConstant.DMS_PERSONAL_ROOT.equals(rootDocument.getDocumentName()) && rootDocument.getOwnerID().intValue() == sessionContainer.getUserRecordID().intValue())) {
      if (oldcheckoutHistory != null) {  //by pass the check in person checking
        if (!DmsOperationConstant.DMS_RECORD_EMPTY.equals(document.getRecordStatus())){
          if (!sessionContainer.getUserRecordID().equals(oldcheckoutHistory.getCheckoutPersonID())) {
            throw new IdentityMismatchException(DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH);
          }
        }
      } else {
        throw new UncheckinableException(DmsErrorConstant.CHECKIN_INAVAILABLE);
      }
    }
    if(!Utility.isEmpty(currentLocker)){
    DmsCheckoutHistory checkoutHistory = (DmsCheckoutHistory) currentLocker.get(0);
    checkoutHistory.setCheckoutStatus(DmsCheckoutHistory.HISTORY_RECORD);
    checkoutHistory.setCheckinTime(new Timestamp(System.currentTimeMillis()));
    historyDAO.updateObject(checkoutHistory);
    }
    historyDAO=null;

    // log down in audit trail
    if (sessionContainer.getUserRecordID() != null && sessionContainer.getSessionID()!=null  && (!DmsDocument.TIF_ANNOTATION_TYPE.equals(document.getDocumentType()))) {
      AuditTrailManager auditManager = new AuditTrailManager(sessionContainer, conn);
      auditManager.auditTrail(GlobalConstant.OBJECT_TYPE_DOCUMENT, document, AuditTrailConstant.ACCESS_TYPE_CHECK_IN, document.getVersionNumber());
      auditManager.release();
    }

    return dmsVersion;
  }

  /**
   * Gets the DmsCheckoutHistory object by the dmsDocument and dmsVersion object
   * @param dmsDocument the dmsDocument object
   * @param version  the dmsVersion Object
   * @return the DmsCheckoutHistory object
   * @throws ApplicationException
   * @see com.dcivision.dms.bean.DmsVersion
   */
  public DmsCheckoutHistory getCurrentCheckoutDetail(DmsDocument dmsDocument, String version) throws ApplicationException {
    DmsVersionDAObject dmsVersionDAO = new DmsVersionDAObject(sessionContainer, conn);
    DmsVersion dmsVersion = null;
    if (DmsOperationConstant.DMS_TOP_VERSION.equals(version)) {
      dmsVersion =(DmsVersion) dmsVersionDAO.getTopVersionByDocumentID(dmsDocument.getID());
    }else {
      Integer versionID = TextUtility.parseIntegerObj(version);
      dmsVersion =(DmsVersion) dmsVersionDAO.getObjectByID(versionID);
    }
    DmsCheckoutHistoryDAObject historyDAO = new DmsCheckoutHistoryDAObject(sessionContainer, conn);
    List currentLocker = historyDAO.getObjectByVersionAndCheckoutStatus(dmsVersion.getID(), DmsCheckoutHistory.CURRENT_RECORD);
    historyDAO=null;
    if (currentLocker.size() == 1) {
      return (DmsCheckoutHistory) currentLocker.get(0);
    }
    else {
      return null;
    }
  }

  
  /**
   * Checks the checkout dmsDocument user is the same person with the current user. 
   * @param documentID   the ID of dmsDocument object that checkout
   * @return true if same person, false if not the same person or the document is not checkout before
   * @throws ApplicationException
   * @see com.dcivision.dms.core.VersionControlManage#isCurrentCheckoutPerson(Integer documentID, Integer userID, String version)
   */
  public boolean isCurrentCheckoutPerson(Integer documentID) throws ApplicationException {
    return this.isCurrentCheckoutPerson(documentID, sessionContainer.getUserRecordID(), DmsOperationConstant.DMS_TOP_VERSION);
  }

  /**
   * Checks the user that check out the document before is the same person with the specified use and specified version.
   * 
   * @param documentID the ID of dmsDocument object that checkout
   * @param userID     the user record ID
   * @param version    the dmsVersion ID
   * @return true if same person, false if not the same person or the document is not checkout before
   * @throws ApplicationException
   */
  public boolean isCurrentCheckoutPerson(Integer documentID, Integer userID, String version) throws ApplicationException {
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsDocument document = (DmsDocument) dmsDocumentDAO.getObjectByID(documentID);
    DmsCheckoutHistory checkoutHistory = getCurrentCheckoutDetail(document, version);
    dmsDocumentDAO=null;
    if (checkoutHistory != null) {
      if (!userID.equals(checkoutHistory.getCheckoutPersonID())) {
        return false;
      }
      else {
        return true;
      }
    }
    else {
      return false;
    }
  }

  /**
   * Gets the DmsCheckoutHistory object by the DmsCheckoutHistory ID
   * 
   * @param id the DmsCheckoutHistory object ID
   * @return the DmsCheckoutHistory object
   * @throws ApplicationException
   */
  public DmsCheckoutHistory getCheckoutHistory(Integer id) throws ApplicationException {
    DmsCheckoutHistoryDAObject historyDAO = new DmsCheckoutHistoryDAObject(sessionContainer, conn);
    DmsCheckoutHistory history = (DmsCheckoutHistory) historyDAO.getObjectByID(id);
    historyDAO=null;
    return history;
  }

  /**
   * Indexes the document related information to Db storage and the Lucene index storage
   *
   * @param dmsDocument      The document object.
   * @param data             The document data stream.
   * @param mode             The mode of operation.
   * @throws ApplicationException
   * @deprecated This method has deprecated.
   */
  
  public void indexDocument(DmsDocument dmsDocument, InputStream data, String mode) throws ApplicationException {
    this.indexDocument(dmsDocument, data, mode, null);
  }

  /**
   * Indexes the document related information to Db storage and the Lucene index storage
   *
   * @param dmsDocument      The document object.
   * @param data             The document data stream.
   * @param mode             The mode of operation.
   * @param fields           The fields need to be updated. (Applicable for UPDATE MODE Only)
   * @param excludeFlag      Whether the "fields" arguments are excluding fields. (Applicable for UPDATE MODE Only)
   * @throws ApplicationException
   * @deprecated This method has deprecated.
   */
  
  public void indexDocument(DmsDocument dmsDocument, InputStream data, String mode, String[] fields) throws ApplicationException {
    log.info("Index Document Function Begin");
    
    DocumentRetrievalManager retrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    List docDetailList =  dmsDocument.getDocumentDetails();

    if (Utility.isEmpty(docDetailList)){
      docDetailList=retrievalManager.getDocumentDetailList(dmsDocument.getID());
      dmsDocument.setDocumentDetails(docDetailList);

      if(!Utility.isEmpty(docDetailList)){
      //DmsDocumentDetail tmpDetail = (DmsDocumentDetail)docDetailList.get(0);
        dmsDocument.setUserDefinedFieldID(((DmsDocumentDetail)docDetailList.get(0)).getUserDefinedFieldID());
      }
    }
    
    
    if (data == null) {
      IndexManager idxHandler = FullTextIndexFactory.getInstance();
      if (GlobalConstant.OP_MODE_INSERT.equals(mode)) {
        idxHandler.insertDocument(DmsIndexConverter.getIndexDocument(dmsDocument, data));
      } else if (GlobalConstant.OP_MODE_UPDATE.equals(mode)) {
        org.apache.lucene.document.Document doc = DmsIndexConverter.getIndexDocument(dmsDocument, data, fields);
        idxHandler.updateDocument(doc);
      } else if (GlobalConstant.OP_MODE_DELETE.equals(mode)) {
        idxHandler.deleteDocument(DmsIndexConverter.getIndexDocument(dmsDocument, data));
      }
    } else {
      IndexBackgroundThread ibt = new IndexBackgroundThread(dmsDocument, data, mode, fields);
      ibt.start();
    }
    
    log.info("Index Document Function End");
    retrievalManager.release();
  }

  /**
   * Checkin a document and create a new document version and update the checkout history.
   * <P>
   * for webdav checkin Document. just remove the "docValidateManager.checkDocumentIsEmptyContent(data);" check.
   * </P>
   * @param autoLabel                 true if update the version label by system LabelManager
   * @param checkinType               DmsOperationConstant.CREATE_NEW_CHECKIN
   * @param documentID                the dmsDocument Object ID for checkin
   * @param version                   new version of the checkin document
   * @param data                      InputStream data of the checkin document
   * @return new version create after checkin
   * @throws IdentityMismatchException it is thrown if the checkin user not same as the checkout user
   * <pre>
   *   IdentityMismatchException with the following message codes will be thrown
   *   DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH
   * </pre>
   * @throws UncheckinableException it is thrown if checkin a document that is not checkout(Except the document in 
   *                                personal)
   * <pre>
   * UncheckinableException with the following message codes will be thrown
   * DmsErrorConstant.CHECKIN_INAVAILABLE
   * </pre>
   * @throws ApplicationException
   * @see com.dcivision.dms.core.labelManager
   * @see com.dcivision.dms.bean.DmsVersion
   */  
  public DmsVersion webdavCheckinDocument(boolean autoLabel, String checkinType, Integer documentID, DmsVersion version, InputStream data) throws IdentityMismatchException, UncheckinableException, ApplicationException {
    InputStream fullTextFileInputStream = null;
    DocumentValidateManager docValidateManager = new DocumentValidateManager(sessionContainer, conn);
    // check if the uploaded file is empty content or does not exist.
    //docValidateManager.checkDocumentIsEmptyContent(data);
    DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    DmsVersion newVersion = null;
//    try {
      log.info("checkin document ID = " +documentID+" version parent ID -- " + version.getParentID());
      DmsDocument document = (DmsDocument) dmsDocumentDAO.getObjectByID(documentID);
      document.setCurFunctionCode(SystemFunctionConstant.DMS_PUBLIC_FOLDER);
      document.setItemSize(version.getItemSize());
      document.setRealDocumentName(version.getCheckinFileName());
      docValidateManager.checkStorageLimitAvailable(document);
      log.debug("Available space exists for current document");

      DmsCheckoutHistory checkoutHistory = getCurrentCheckoutDetail(document, DmsOperationConstant.DMS_TOP_VERSION);
      DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
      DmsDocument rootDocument = docRetrievalManager.getRootFolderByRootID(document.getRootID());
      if (! (DmsOperationConstant.DMS_PERSONAL_ROOT.equals(rootDocument.getDocumentName()) && rootDocument.getOwnerID().intValue() == sessionContainer.getUserRecordID().intValue())) {
        if (checkoutHistory != null) {  //by pass the check in person checking
          if (!DmsOperationConstant.DMS_RECORD_EMPTY.equals(document.getRecordStatus())){
            if (!sessionContainer.getUserRecordID().equals(checkoutHistory.getCheckoutPersonID())) {
              throw new IdentityMismatchException(DmsErrorConstant.CHECKIN_IDENTITY_MISMATCH);
            }
          }
        } else {
          throw new UncheckinableException(DmsErrorConstant.CHECKIN_INAVAILABLE);
        }
      }
      LabelManager labelManager = new LabelManager(sessionContainer, conn);
      if (autoLabel) {
        labelManager.setVersion(version);
        labelManager.process();
      }
      if (DmsOperationConstant.DMS_RECORD_EMPTY.equals(document.getRecordStatus())){
        newVersion = this.updateVersionOnEmptyFileContent(document, version, data, fullTextFileInputStream);
      }else{
        newVersion = this.createVersion(document, version, data);
      }
      DmsCheckoutHistoryDAObject historyDAO = new DmsCheckoutHistoryDAObject(sessionContainer, conn);
      if (GlobalConstant.RECORD_PENDING.equals(version.getRecordStatus()) //not update checkout status and item status, update from Workflow
          && DmsOperationConstant.CREATE_NEW_CHECKIN.equals(checkinType)) { //For Record with and Major Workflow.
        /* List historyList = historyDAO.getObjectByVersionAndCheckoutStatus(version.getID(), DmsCheckoutHistory.CURRENT_RECORD);
         DmsCheckoutHistory history = (DmsCheckoutHistory) historyList.get(0);*/
        //history.setCheckoutStatus(DmsCheckoutHistory.HISTORY_RECORD);
        checkoutHistory.setCheckinTime(new Timestamp(System.currentTimeMillis()));
        historyDAO.updateObject(checkoutHistory);

      } else { //without workflow or personal folder
        // resume the items status
        newVersion.setItemStatus(DmsVersion.AVAILABLE_STATUS);
        //TODO: itemDAO.updateObject(newVersion);
        if (! (DmsOperationConstant.DMS_PERSONAL_ROOT.equals(rootDocument.getDocumentName())
               && rootDocument.getOwnerID().intValue() == sessionContainer.getUserRecordID().intValue())) {

          /*List historyList = historyDAO.getObjectByVersionAndCheckoutStatus(version.getID(), DmsCheckoutHistory.CURRENT_RECORD);
           log.debug("historyList = " + historyList.size());
               DmsCheckoutHistory history = (DmsCheckoutHistory) historyList.get(0);*/
          checkoutHistory.setCheckoutStatus(DmsCheckoutHistory.HISTORY_RECORD);
          checkoutHistory.setCheckinTime(new Timestamp(System.currentTimeMillis()));
          historyDAO.updateObject(checkoutHistory);
        }
      }
//log.debug("document.getParentID() = " + document.getParentID());
      //Document Checking Alert
      DmsDocument parentDoc = (DmsDocument) dmsDocumentDAO.getObjectByID(document.getParentID());
      AdapterMaster am = AdapterMasterFactory.getAdapterMaster(sessionContainer, conn);
      try {
        am.call(UpdateAlert.DOCUMENT_TYPE, parentDoc.getID(), UpdateAlert.UPDATE_ACTION, document.getDocumentName(), null, null, null, document.getID());
        am.call(UpdateAlert.DOCUMENT_TYPE, document.getID(), UpdateAlert.UPDATE_ACTION, document.getDocumentName(), null, null, null);
        if(docRetrievalManager.hasRelationship(document.getID(),null)){
          MtmDocumentRelationshipDAObject dmsMtmDocumentRelationshipDAO = new MtmDocumentRelationshipDAObject (sessionContainer, conn);
          AlertManager alertManager = new AlertManager(sessionContainer, conn);
          List relationList=dmsMtmDocumentRelationshipDAO.getListByIDRelationType(document.getID(),null);
          List inRelationList=dmsMtmDocumentRelationshipDAO.getListByRelationIDRelationType(document.getID(),null);
          List alertList=new ArrayList();
          if(!Utility.isEmpty(relationList)){
            for(int i=0;i<relationList.size();i++){
              alertList = alertManager.listUpdateAlertByObjectTypeObjectIDAndAction(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)relationList.get(i)).getDocumentID(),UpdateAlert.MODIFY_RELATED_DOC);
              if(!Utility.isEmpty(alertList)){
                am.call(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)relationList.get(i)).getDocumentID(),UpdateAlert.MODIFY_RELATED_DOC,document.getDocumentName(),
               null,null,null,document.getID());
              }
            }
          }
          if(!Utility.isEmpty(inRelationList)){
            for(int i=0;i<inRelationList.size();i++){
              alertList= alertManager.listUpdateAlertByObjectTypeObjectIDAndAction(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)inRelationList.get(i)).getRelatedDocumentID(),UpdateAlert.MODIFY_RELATED_DOC);
              if(!Utility.isEmpty(alertList)){
                am.call(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)inRelationList.get(i)).getRelatedDocumentID(),UpdateAlert.MODIFY_RELATED_DOC,document.getDocumentName(),
               null,null,null,document.getID());
              }
            }
      }
    }
        am.release();
      } catch (Exception e) {
        log.error(e, e);
      }

      // log down in audit trail
      if (sessionContainer.getUserRecordID() != null && sessionContainer.getSessionID()!=null  && (!DmsDocument.TIF_ANNOTATION_TYPE.equals(document.getDocumentType()))) {
        AuditTrailManager auditManager = new AuditTrailManager(sessionContainer, conn);
        auditManager.auditTrail(GlobalConstant.OBJECT_TYPE_DOCUMENT, document, AuditTrailConstant.ACCESS_TYPE_CHECK_IN, newVersion.getVersionNumber());
        auditManager.release();
      }
      dmsDocumentDAO=null;
      historyDAO=null;
      docValidateManager.release();

      return newVersion;
  }

  /**
    * Checks the checkout dmsDocument user is the same person with the specified user. 
    * @param documentID   the ID of dmsDocument object that checkout
    * @param userID       the specified user ID
    * @return true if same person, false if not the same person or the document is not checkout before
    * @throws ApplicationException
    * @see com.dcivision.dms.core.VersionControlManage#isCurrentCheckoutPerson(Integer documentID, Integer userID, String version)
    */
  public boolean isCurrentCheckoutPerson(Integer documentID,Integer userID) throws ApplicationException {
    return this.isCurrentCheckoutPerson(documentID, userID, DmsOperationConstant.DMS_TOP_VERSION);
  }  
  
}
